home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / ice / pisces / byacc / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-04  |  29.8 KB  |  1,772 lines

  1. #include "defs.h"
  2.  
  3. /*  The line size must be a positive integer.  One hundred was chosen    */
  4. /*  because few lines in Yacc input grammars exceed 100 characters.    */
  5. /*  Note that if a line exceeds LINESIZE characters, the line buffer    */
  6. /*  will be expanded to accomodate it.                    */
  7.  
  8. #define LINESIZE 100
  9.  
  10. char *cache;
  11. int cinc, cache_size;
  12.  
  13. int ntags, tagmax;
  14. char **tag_table;
  15.  
  16. char saw_eof, unionized;
  17. char *cptr, *line;
  18. int linesize;
  19.  
  20. bucket *goal;
  21. int prec;
  22. int gensym;
  23. char last_was_action;
  24.  
  25. int maxitems;
  26. bucket **pitem;
  27.  
  28. int maxrules;
  29. bucket **plhs;
  30.  
  31. int name_pool_size;
  32. char *name_pool;
  33.  
  34. char line_format[] = "#line %d \"%s\"\n";
  35.  
  36.  
  37. cachec(c)
  38. int c;
  39. {
  40.     assert(cinc >= 0);
  41.     if (cinc >= cache_size)
  42.     {
  43.     cache_size += 256;
  44.     cache = REALLOC(cache, cache_size);
  45.     if (cache == 0) no_space();
  46.     }
  47.     cache[cinc] = c;
  48.     ++cinc;
  49. }
  50.  
  51.  
  52. get_line()
  53. {
  54.     register FILE *f = input_file;
  55.     register int c;
  56.     register int i;
  57.  
  58.     if (saw_eof || (c = getc(f)) == EOF)
  59.     {
  60.     if (line) { FREE(line); line = 0; }
  61.     cptr = 0;
  62.     saw_eof = 1;
  63.     return;
  64.     }
  65.  
  66.     if (line == 0 || linesize != (LINESIZE + 1))
  67.     {
  68.     if (line) FREE(line);
  69.     linesize = LINESIZE + 1;
  70.     line = MALLOC(linesize);
  71.     if (line == 0) no_space();
  72.     }
  73.  
  74.     i = 0;
  75.     ++lineno;
  76.     for (;;)
  77.     {
  78.     line[i]  =  c;
  79.     if (c == '\n') { cptr = line; return; }
  80.     if (++i >= linesize)
  81.     {
  82.         linesize += LINESIZE;
  83.         line = REALLOC(line, linesize);
  84.         if (line ==  0) no_space();
  85.     }
  86.     c = getc(f);
  87.     if (c ==  EOF)
  88.     {
  89.         line[i] = '\n';
  90.         saw_eof = 1;
  91.         cptr = line;
  92.         return;
  93.     }
  94.     }
  95. }
  96.  
  97.  
  98. char *
  99. dup_line()
  100. {
  101.     register char *p, *s, *t;
  102.  
  103.     if (line == 0) return (0);
  104.     s = line;
  105.     while (*s != '\n') ++s;
  106.     p = MALLOC(s - line + 1);
  107.     if (p == 0) no_space();
  108.  
  109.     s = line;
  110.     t = p;
  111.     while ((*t++ = *s++) != '\n') continue;
  112.     return (p);
  113. }
  114.  
  115.  
  116. skip_comment()
  117. {
  118.     register char *s;
  119.  
  120.     int st_lineno = lineno;
  121.     char *st_line = dup_line();
  122.     char *st_cptr = st_line + (cptr - line);
  123.  
  124.     s = cptr + 2;
  125.     for (;;)
  126.     {
  127.     if (*s == '*' && s[1] == '/')
  128.     {
  129.         cptr = s + 2;
  130.         FREE(st_line);
  131.         return;
  132.     }
  133.     if (*s == '\n')
  134.     {
  135.         get_line();
  136.         if (line == 0)
  137.         unterminated_comment(st_lineno, st_line, st_cptr);
  138.         s = cptr;
  139.     }
  140.     else
  141.         ++s;
  142.     }
  143. }
  144.  
  145.  
  146. int
  147. nextc()
  148. {
  149.     register char *s;
  150.  
  151.     if (line == 0)
  152.     {
  153.     get_line();
  154.     if (line == 0)
  155.         return (EOF);
  156.     }
  157.  
  158.     s = cptr;
  159.     for (;;)
  160.     {
  161.     switch (*s)
  162.     {
  163.     case '\n':
  164.         get_line();
  165.         if (line == 0) return (EOF);
  166.         s = cptr;
  167.         break;
  168.  
  169.     case ' ':
  170.     case '\t':
  171.     case '\f':
  172.     case '\r':
  173.     case '\v':
  174.     case ',':
  175.     case ';':
  176.         ++s;
  177.         break;
  178.  
  179.     case '\\':
  180.         cptr = s;
  181.         return ('%');
  182.  
  183.     case '/':
  184.         if (s[1] == '*')
  185.         {
  186.         cptr = s;
  187.         skip_comment();
  188.         s = cptr;
  189.         break;
  190.         }
  191.         else if (s[1] == '/')
  192.         {
  193.         get_line();
  194.         if (line == 0) return (EOF);
  195.         s = cptr;
  196.         break;
  197.         }
  198.         /* fall through */
  199.  
  200.     default:
  201.         cptr = s;
  202.         return (*s);
  203.     }
  204.     }
  205. }
  206.  
  207.  
  208. int
  209. keyword()
  210. {
  211.     register int c;
  212.     char *t_cptr = cptr;
  213.  
  214.     c = *++cptr;
  215.     if (isalpha(c))
  216.     {
  217.     cinc = 0;
  218.     for (;;)
  219.     {
  220.         if (isalpha(c))
  221.         {
  222.         if (isupper(c)) c = tolower(c);
  223.         cachec(c);
  224.         }
  225.         else if (isdigit(c) || c == '_' || c == '.' || c == '$')
  226.         cachec(c);
  227.         else
  228.         break;
  229.         c = *++cptr;
  230.     }
  231.     cachec(NUL);
  232.  
  233.     if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  234.         return (TOKEN);
  235.     if (strcmp(cache, "type") == 0)
  236.         return (TYPE);
  237.     if (strcmp(cache, "left") == 0)
  238.         return (LEFT);
  239.     if (strcmp(cache, "right") == 0)
  240.         return (RIGHT);
  241.     if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  242.         return (NONASSOC);
  243.     if (strcmp(cache, "start") == 0)
  244.         return (START);
  245.     if (strcmp(cache, "union") == 0)
  246.         return (UNION);
  247.     if (strcmp(cache, "ident") == 0)
  248.         return (IDENT);
  249.     }
  250.     else
  251.     {
  252.     ++cptr;
  253.     if (c == '{')
  254.         return (TEXT);
  255.     if (c == '%' || c == '\\')
  256.         return (MARK);
  257.     if (c == '<')
  258.         return (LEFT);
  259.     if (c == '>')
  260.         return (RIGHT);
  261.     if (c == '0')
  262.         return (TOKEN);
  263.     if (c == '2')
  264.         return (NONASSOC);
  265.     }
  266.     syntax_error(lineno, line, t_cptr);
  267.     /*NOTREACHED*/
  268. }
  269.  
  270.  
  271. copy_ident()
  272. {
  273.     register int c;
  274.     register FILE *f = output_file;
  275.  
  276.     c = nextc();
  277.     if (c == EOF) unexpected_EOF();
  278.     if (c != '"') syntax_error(lineno, line, cptr);
  279.     ++outline;
  280.     fprintf(f, "#ident \"");
  281.     for (;;)
  282.     {
  283.     c = *++cptr;
  284.     if (c == '\n')
  285.     {
  286.         fprintf(f, "\"\n");
  287.         return;
  288.     }
  289.     putc(c, f);
  290.     if (c == '"')
  291.     {
  292.         putc('\n', f);
  293.         ++cptr;
  294.         return;
  295.     }
  296.     }
  297. }
  298.  
  299.  
  300. copy_text()
  301. {
  302.     register int c;
  303.     int quote;
  304.     register FILE *f = text_file;
  305.     int need_newline = 0;
  306.     int t_lineno = lineno;
  307.     char *t_line = dup_line();
  308.     char *t_cptr = t_line + (cptr - line - 2);
  309.  
  310.     if (*cptr == '\n')
  311.     {
  312.     get_line();
  313.     if (line == 0)
  314.         unterminated_text(t_lineno, t_line, t_cptr);
  315.     }
  316.     if (!lflag) fprintf(f, line_format, lineno, input_file_name);
  317.  
  318. loop:
  319.     c = *cptr++;
  320.     switch (c)
  321.     {
  322.     case '\n':
  323.     next_line:
  324.     putc('\n', f);
  325.     need_newline = 0;
  326.     get_line();
  327.     if (line) goto loop;
  328.     unterminated_text(t_lineno, t_line, t_cptr);
  329.  
  330.     case '\'':
  331.     case '"':
  332.     {
  333.         int s_lineno = lineno;
  334.         char *s_line = dup_line();
  335.         char *s_cptr = s_line + (cptr - line - 1);
  336.  
  337.         quote = c;
  338.         putc(c, f);
  339.         for (;;)
  340.         {
  341.         c = *cptr++;
  342.         putc(c, f);
  343.         if (c == quote)
  344.         {
  345.             need_newline = 1;
  346.             FREE(s_line);
  347.             goto loop;
  348.         }
  349.         if (c == '\n')
  350.             unterminated_string(s_lineno, s_line, s_cptr);
  351.         if (c == '\\')
  352.         {
  353.             c = *cptr++;
  354.             putc(c, f);
  355.             if (c == '\n')
  356.             {
  357.             get_line();
  358.             if (line == 0)
  359.                 unterminated_string(s_lineno, s_line, s_cptr);
  360.             }
  361.         }
  362.         }
  363.     }
  364.  
  365.     case '/':
  366.     putc(c, f);
  367.     need_newline = 1;
  368.     c = *cptr;
  369.     if (c == '/')
  370.     {
  371.         putc('*', f);
  372.         while ((c = *++cptr) != '\n')
  373.         {
  374.         if (c == '*' && cptr[1] == '/')
  375.             fprintf(f, "* ");
  376.         else
  377.             putc(c, f);
  378.         }
  379.         fprintf(f, "*/");
  380.         goto next_line;
  381.     }
  382.     if (c == '*')
  383.     {
  384.         int c_lineno = lineno;
  385.         char *c_line = dup_line();
  386.         char *c_cptr = c_line + (cptr - line - 1);
  387.  
  388.         putc('*', f);
  389.         ++cptr;
  390.         for (;;)
  391.         {
  392.         c = *cptr++;
  393.         putc(c, f);
  394.         if (c == '*' && *cptr == '/')
  395.         {
  396.             putc('/', f);
  397.             ++cptr;
  398.             FREE(c_line);
  399.             goto loop;
  400.         }
  401.         if (c == '\n')
  402.         {
  403.             get_line();
  404.             if (line == 0)
  405.             unterminated_comment(c_lineno, c_line, c_cptr);
  406.         }
  407.         }
  408.     }
  409.     putc('/', f);
  410.     need_newline = 1;
  411.     goto loop;
  412.  
  413.     case '%':
  414.     case '\\':
  415.     if (*cptr == '}')
  416.     {
  417.         if (need_newline) putc('\n', f);
  418.         ++cptr;
  419.         FREE(t_line);
  420.         return;
  421.     }
  422.     /* fall through */
  423.  
  424.     default:
  425.     putc(c, f);
  426.     need_newline = 1;
  427.     goto loop;
  428.     }
  429. }
  430.  
  431.  
  432. copy_union()
  433. {
  434.     register int c;
  435.     int quote;
  436.     int depth;
  437.     int u_lineno = lineno;
  438.     char *u_line = dup_line();
  439.     char *u_cptr = u_line + (cptr - line - 6);
  440.  
  441.     if (unionized) over_unionized(cptr - 6);
  442.     unionized = 1;
  443.  
  444.     if (!lflag)
  445.     fprintf(text_file, line_format, lineno, input_file_name);
  446.  
  447.     fprintf(text_file, "typedef union");
  448.     if (dflag) fprintf(union_file, "typedef union");
  449.  
  450.     depth = 0;
  451. loop:
  452.     c = *cptr++;
  453.     putc(c, text_file);
  454.     if (dflag) putc(c, union_file);
  455.     switch (c)
  456.     {
  457.     case '\n':
  458.     next_line:
  459.     get_line();
  460.     if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  461.     goto loop;
  462.  
  463.     case '{':
  464.     ++depth;
  465.     goto loop;
  466.  
  467.     case '}':
  468.     if (--depth == 0)
  469.     {
  470.         fprintf(text_file, " YYSTYPE;\n");
  471.         FREE(u_line);
  472.         return;
  473.     }
  474.     goto loop;
  475.  
  476.     case '\'':
  477.     case '"':
  478.     {
  479.         int s_lineno = lineno;
  480.         char *s_line = dup_line();
  481.         char *s_cptr = s_line + (cptr - line - 1);
  482.  
  483.         quote = c;
  484.         for (;;)
  485.         {
  486.         c = *cptr++;
  487.         putc(c, text_file);
  488.         if (dflag) putc(c, union_file);
  489.         if (c == quote)
  490.         {
  491.             FREE(s_line);
  492.             goto loop;
  493.         }
  494.         if (c == '\n')
  495.             unterminated_string(s_lineno, s_line, s_cptr);
  496.         if (c == '\\')
  497.         {
  498.             c = *cptr++;
  499.             putc(c, text_file);
  500.             if (dflag) putc(c, union_file);
  501.             if (c == '\n')
  502.             {
  503.             get_line();
  504.             if (line == 0)
  505.                 unterminated_string(s_lineno, s_line, s_cptr);
  506.             }
  507.         }
  508.         }
  509.     }
  510.  
  511.     case '/':
  512.     c = *cptr;
  513.     if (c == '/')
  514.     {
  515.         putc('*', text_file);
  516.         if (dflag) putc('*', union_file);
  517.         while ((c = *++cptr) != '\n')
  518.         {
  519.         if (c == '*' && cptr[1] == '/')
  520.         {
  521.             fprintf(text_file, "* ");
  522.             if (dflag) fprintf(union_file, "* ");
  523.         }
  524.         else
  525.         {
  526.             putc(c, text_file);
  527.             if (dflag) putc(c, union_file);
  528.         }
  529.         }
  530.         fprintf(text_file, "*/\n");
  531.         if (dflag) fprintf(union_file, "*/\n");
  532.         goto next_line;
  533.     }
  534.     if (c == '*')
  535.     {
  536.         int c_lineno = lineno;
  537.         char *c_line = dup_line();
  538.         char *c_cptr = c_line + (cptr - line - 1);
  539.  
  540.         putc('*', text_file);
  541.         if (dflag) putc('*', union_file);
  542.         ++cptr;
  543.         for (;;)
  544.         {
  545.         c = *cptr++;
  546.         putc(c, text_file);
  547.         if (dflag) putc(c, union_file);
  548.         if (c == '*' && *cptr == '/')
  549.         {
  550.             putc('/', text_file);
  551.             if (dflag) putc('/', union_file);
  552.             ++cptr;
  553.             FREE(c_line);
  554.             goto loop;
  555.         }
  556.         if (c == '\n')
  557.         {
  558.             get_line();
  559.             if (line == 0)
  560.             unterminated_comment(c_lineno, c_line, c_cptr);
  561.         }
  562.         }
  563.     }
  564.     goto loop;
  565.  
  566.     default:
  567.     goto loop;
  568.     }
  569. }
  570.  
  571.  
  572. int
  573. hexval(c)
  574. int c;
  575. {
  576.     if (c >= '0' && c <= '9')
  577.     return (c - '0');
  578.     if (c >= 'A' && c <= 'F')
  579.     return (c - 'A' + 10);
  580.     if (c >= 'a' && c <= 'f')
  581.     return (c - 'a' + 10);
  582.     return (-1);
  583. }
  584.  
  585.  
  586. bucket *
  587. get_literal()
  588. {
  589.     register int c, quote;
  590.     register int i;
  591.     register int n;
  592.     register char *s;
  593.     register bucket *bp;
  594.     int s_lineno = lineno;
  595.     char *s_line = dup_line();
  596.     char *s_cptr = s_line + (cptr - line);
  597.  
  598.     quote = *cptr++;
  599.     cinc = 0;
  600.     for (;;)
  601.     {
  602.     c = *cptr++;
  603.     if (c == quote) break;
  604.     if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  605.     if (c == '\\')
  606.     {
  607.         char *c_cptr = cptr - 1;
  608.  
  609.         c = *cptr++;
  610.         switch (c)
  611.         {
  612.         case '\n':
  613.         get_line();
  614.         if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  615.         continue;
  616.  
  617.         case '0': case '1': case '2': case '3':
  618.         case '4': case '5': case '6': case '7':
  619.         n = c - '0';
  620.         c = *cptr;
  621.         if (IS_OCTAL(c))
  622.         {
  623.             n = (n << 3) + (c - '0');
  624.             c = *++cptr;
  625.             if (IS_OCTAL(c))
  626.             {
  627.             n = (n << 3) + (c - '0');
  628.             ++cptr;
  629.             }
  630.         }
  631.         if (n > MAXCHAR) illegal_character(c_cptr);
  632.         c = n;
  633.             break;
  634.  
  635.         case 'x':
  636.         c = *cptr++;
  637.         n = hexval(c);
  638.         if (n < 0 || n >= 16)
  639.             illegal_character(c_cptr);
  640.         for (;;)
  641.         {
  642.             c = *cptr;
  643.             i = hexval(c);
  644.             if (i < 0 || i >= 16) break;
  645.             ++cptr;
  646.             n = (n << 4) + i;
  647.             if (n > MAXCHAR) illegal_character(c_cptr);
  648.         }
  649.         c = n;
  650.         break;
  651.  
  652.         case 'a': c = 7; break;
  653.         case 'b': c = '\b'; break;
  654.         case 'f': c = '\f'; break;
  655.         case 'n': c = '\n'; break;
  656.         case 'r': c = '\r'; break;
  657.         case 't': c = '\t'; break;
  658.         case 'v': c = '\v'; break;
  659.         }
  660.     }
  661.     cachec(c);
  662.     }
  663.     FREE(s_line);
  664.  
  665.     n = cinc;
  666.     s = MALLOC(n);
  667.     if (s == 0) no_space();
  668.     
  669.     for (i = 0; i < n; ++i)
  670.     s[i] = cache[i];
  671.  
  672.     cinc = 0;
  673.     if (n == 1)
  674.     cachec('\'');
  675.     else
  676.     cachec('"');
  677.  
  678.     for (i = 0; i < n; ++i)
  679.     {
  680.     c = ((unsigned char *)s)[i];
  681.     if (c == '\\' || c == cache[0])
  682.     {
  683.         cachec('\\');
  684.         cachec(c);
  685.     }
  686.     else if (isprint(c))
  687.         cachec(c);
  688.     else
  689.     {
  690.         cachec('\\');
  691.         switch (c)
  692.         {
  693.         case 7: cachec('a'); break;
  694.         case '\b': cachec('b'); break;
  695.         case '\f': cachec('f'); break;
  696.         case '\n': cachec('n'); break;
  697.         case '\r': cachec('r'); break;
  698.         case '\t': cachec('t'); break;
  699.         case '\v': cachec('v'); break;
  700.         default:
  701.         cachec(((c >> 6) & 7) + '0');
  702.         cachec(((c >> 3) & 7) + '0');
  703.         cachec((c & 7) + '0');
  704.         break;
  705.         }
  706.     }
  707.     }
  708.  
  709.     if (n == 1)
  710.     cachec('\'');
  711.     else
  712.     cachec('"');
  713.  
  714.     cachec(NUL);
  715.     bp = lookup(cache);
  716.     bp->class = TERM;
  717.     if (n == 1 && bp->value == UNDEFINED)
  718.     bp->value = *(unsigned char *)s;
  719.     FREE(s);
  720.  
  721.     return (bp);
  722. }
  723.  
  724.  
  725. int
  726. is_reserved(name)
  727. char *name;
  728. {
  729.     char *s;
  730.  
  731.     if (strcmp(name, ".") == 0 ||
  732.         strcmp(name, "$accept") == 0 ||
  733.         strcmp(name, "$end") == 0)
  734.     return (1);
  735.  
  736.     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  737.     {
  738.     s = name + 3;
  739.     while (isdigit(*s)) ++s;
  740.     if (*s == NUL) return (1);
  741.     }
  742.  
  743.     return (0);
  744. }
  745.  
  746.  
  747. bucket *
  748. get_name()
  749. {
  750.     register int c;
  751.  
  752.     cinc = 0;
  753.     for (c = *cptr; IS_IDENT(c); c = *++cptr)
  754.     cachec(c);
  755.     cachec(NUL);
  756.  
  757.     if (is_reserved(cache)) used_reserved(cache);
  758.  
  759.     return (lookup(cache));
  760. }
  761.  
  762.  
  763. int
  764. get_number()
  765. {
  766.     register int c;
  767.     register int n;
  768.  
  769.     n = 0;
  770.     for (c = *cptr; isdigit(c); c = *++cptr)
  771.     n = 10*n + (c - '0');
  772.  
  773.     return (n);
  774. }
  775.  
  776.  
  777. char *
  778. get_tag()
  779. {
  780.     register int c;
  781.     register int i;
  782.     register char *s;
  783.     int t_lineno = lineno;
  784.     char *t_line = dup_line();
  785.     char *t_cptr = t_line + (cptr - line);
  786.  
  787.     ++cptr;
  788.     c = nextc();
  789.     if (c == EOF) unexpected_EOF();
  790.     if (!isalpha(c) && c != '_' && c != '$')
  791.     illegal_tag(t_lineno, t_line, t_cptr);
  792.  
  793.     cinc = 0;
  794.     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
  795.     cachec(NUL);
  796.  
  797.     c = nextc();
  798.     if (c == EOF) unexpected_EOF();
  799.     if (c != '>')
  800.     illegal_tag(t_lineno, t_line, t_cptr);
  801.     ++cptr;
  802.  
  803.     for (i = 0; i < ntags; ++i)
  804.     {
  805.     if (strcmp(cache, tag_table[i]) == 0)
  806.         return (tag_table[i]);
  807.     }
  808.  
  809.     if (ntags >= tagmax)
  810.     {
  811.     tagmax += 16;
  812.     tag_table = (char **)
  813.             (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  814.                    : MALLOC(tagmax*sizeof(char *)));
  815.     if (tag_table == 0) no_space();
  816.     }
  817.  
  818.     s = MALLOC(cinc);
  819.     if  (s == 0) no_space();
  820.     strcpy(s, cache);
  821.     tag_table[ntags] = s;
  822.     ++ntags;
  823.     FREE(t_line);
  824.     return (s);
  825. }
  826.  
  827.  
  828. declare_tokens(assoc)
  829. int assoc;
  830. {
  831.     register int c;
  832.     register bucket *bp;
  833.     int value;
  834.     char *tag = 0;
  835.  
  836.     if (assoc != TOKEN) ++prec;
  837.  
  838.     c = nextc();
  839.     if (c == EOF) unexpected_EOF();
  840.     if (c == '<')
  841.     {
  842.     tag = get_tag();
  843.     c = nextc();
  844.     if (c == EOF) unexpected_EOF();
  845.     }
  846.  
  847.     for (;;)
  848.     {
  849.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  850.         bp = get_name();
  851.     else if (c == '\'' || c == '"')
  852.         bp = get_literal();
  853.     else
  854.         return;
  855.  
  856.     if (bp == goal) tokenized_start(bp->name);
  857.     bp->class = TERM;
  858.  
  859.     if (tag)
  860.     {
  861.         if (bp->tag && tag != bp->tag)
  862.         retyped_warning(bp->name);
  863.         bp->tag = tag;
  864.     }
  865.  
  866.     if (assoc != TOKEN)
  867.     {
  868.         if (bp->prec && prec != bp->prec)
  869.         reprec_warning(bp->name);
  870.         bp->assoc = assoc;
  871.         bp->prec = prec;
  872.     }
  873.  
  874.     c = nextc();
  875.     if (c == EOF) unexpected_EOF();
  876.     value = UNDEFINED;
  877.     if (isdigit(c))
  878.     {
  879.         value = get_number();
  880.         if (bp->value != UNDEFINED && value != bp->value)
  881.         revalued_warning(bp->name);
  882.         bp->value = value;
  883.         c = nextc();
  884.         if (c == EOF) unexpected_EOF();
  885.     }
  886.     }
  887. }
  888.  
  889.  
  890. declare_types()
  891. {
  892.     register int c;
  893.     register bucket *bp;
  894.     char *tag;
  895.  
  896.     c = nextc();
  897.     if (c == EOF) unexpected_EOF();
  898.     if (c != '<') syntax_error(lineno, line, cptr);
  899.     tag = get_tag();
  900.  
  901.     for (;;)
  902.     {
  903.     c = nextc();
  904.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  905.         bp = get_name();
  906.     else if (c == '\'' || c == '"')
  907.         bp = get_literal();
  908.     else
  909.         return;
  910.  
  911.     if (bp->tag && tag != bp->tag)
  912.         retyped_warning(bp->name);
  913.     bp->tag = tag;
  914.     }
  915. }
  916.  
  917.  
  918. declare_start()
  919. {
  920.     register int c;
  921.     register bucket *bp;
  922.  
  923.     c = nextc();
  924.     if (c == EOF) unexpected_EOF();
  925.     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  926.     syntax_error(lineno, line, cptr);
  927.     bp = get_name();
  928.     if (bp->class == TERM)
  929.     terminal_start(bp->name);
  930.     if (goal && goal != bp)
  931.     restarted_warning();
  932.     goal = bp;
  933. }
  934.  
  935.  
  936. read_declarations()
  937. {
  938.     register int c, k;
  939.  
  940.     cache_size = 256;
  941.     cache = MALLOC(cache_size);
  942.     if (cache == 0) no_space();
  943.  
  944.     for (;;)
  945.     {
  946.     c = nextc();
  947.     if (c == EOF) unexpected_EOF();
  948.     if (c != '%') syntax_error(lineno, line, cptr);
  949.     switch (k = keyword())
  950.     {
  951.     case MARK:
  952.         return;
  953.  
  954.     case IDENT:
  955.         copy_ident();
  956.         break;
  957.  
  958.     case TEXT:
  959.         copy_text();
  960.         break;
  961.  
  962.     case UNION:
  963.         copy_union();
  964.         break;
  965.  
  966.     case TOKEN:
  967.     case LEFT:
  968.     case RIGHT:
  969.     case NONASSOC:
  970.         declare_tokens(k);
  971.         break;
  972.  
  973.     case TYPE:
  974.         declare_types();
  975.         break;
  976.  
  977.     case START:
  978.         declare_start();
  979.         break;
  980.     }
  981.     }
  982. }
  983.  
  984.  
  985. initialize_grammar()
  986. {
  987.     nitems = 4;
  988.     maxitems = 300;
  989.     pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  990.     if (pitem == 0) no_space();
  991.     pitem[0] = 0;
  992.     pitem[1] = 0;
  993.     pitem[2] = 0;
  994.     pitem[3] = 0;
  995.  
  996.     nrules = 3;
  997.     maxrules = 100;
  998.     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  999.     if (plhs == 0) no_space();
  1000.     plhs[0] = 0;
  1001.     plhs[1] = 0;
  1002.     plhs[2] = 0;
  1003.     rprec = (short *) MALLOC(maxrules*sizeof(short));
  1004.     if (rprec == 0) no_space();
  1005.     rprec[0] = 0;
  1006.     rprec[1] = 0;
  1007.     rprec[2] = 0;
  1008.     rassoc = (char *) MALLOC(maxrules*sizeof(char));
  1009.     if (rassoc == 0) no_space();
  1010.     rassoc[0] = TOKEN;
  1011.     rassoc[1] = TOKEN;
  1012.     rassoc[2] = TOKEN;
  1013. }
  1014.  
  1015.  
  1016. expand_items()
  1017. {
  1018.     maxitems += 300;
  1019.     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  1020.     if (pitem == 0) no_space();
  1021. }
  1022.  
  1023.  
  1024. expand_rules()
  1025. {
  1026.     maxrules += 100;
  1027.     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  1028.     if (plhs == 0) no_space();
  1029.     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  1030.     if (rprec == 0) no_space();
  1031.     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  1032.     if (rassoc == 0) no_space();
  1033. }
  1034.  
  1035.  
  1036. advance_to_start()
  1037. {
  1038.     register int c;
  1039.     register bucket *bp;
  1040.     char *s_cptr;
  1041.     int s_lineno;
  1042.  
  1043.     for (;;)
  1044.     {
  1045.     c = nextc();
  1046.     if (c != '%') break;
  1047.     s_cptr = cptr;
  1048.     switch (keyword())
  1049.     {
  1050.     case MARK:
  1051.         no_grammar();
  1052.  
  1053.     case TEXT:
  1054.         copy_text();
  1055.         break;
  1056.  
  1057.     case START:
  1058.         declare_start();
  1059.         break;
  1060.  
  1061.     default:
  1062.         syntax_error(lineno, line, s_cptr);
  1063.     }
  1064.     }
  1065.  
  1066.     c = nextc();
  1067.     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
  1068.     syntax_error(lineno, line, cptr);
  1069.     bp = get_name();
  1070.     if (goal == 0)
  1071.     {
  1072.     if (bp->class == TERM)
  1073.         terminal_start(bp->name);
  1074.     goal = bp;
  1075.     }
  1076.  
  1077.     s_lineno = lineno;
  1078.     c = nextc();
  1079.     if (c == EOF) unexpected_EOF();
  1080.     if (c != ':') syntax_error(lineno, line, cptr);
  1081.     start_rule(bp, s_lineno);
  1082.     ++cptr;
  1083. }
  1084.  
  1085.  
  1086. start_rule(bp, s_lineno)
  1087. register bucket *bp;
  1088. int s_lineno;
  1089. {
  1090.     if (bp->class == TERM)
  1091.     terminal_lhs(s_lineno);
  1092.     bp->class = NONTERM;
  1093.     if (nrules >= maxrules)
  1094.     expand_rules();
  1095.     plhs[nrules] = bp;
  1096.     rprec[nrules] = UNDEFINED;
  1097.     rassoc[nrules] = TOKEN;
  1098. }
  1099.  
  1100.  
  1101. end_rule()
  1102. {
  1103.     register int i;
  1104.  
  1105.     if (!last_was_action && plhs[nrules]->tag)
  1106.     {
  1107.     for (i = nitems - 1; pitem[i]; --i) continue;
  1108.     if (pitem[i+1]->tag != plhs[nrules]->tag)
  1109.         default_action_warning();
  1110.     }
  1111.  
  1112.     last_was_action = 0;
  1113.     if (nitems >= maxitems) expand_items();
  1114.     pitem[nitems] = 0;
  1115.     ++nitems;
  1116.     ++nrules;
  1117. }
  1118.  
  1119.  
  1120. insert_empty_rule()
  1121. {
  1122.     register bucket *bp, **bpp;
  1123.  
  1124.     assert(cache);
  1125.     sprintf(cache, "$$%d", ++gensym);
  1126.     bp = make_bucket(cache);
  1127.     last_symbol->next = bp;
  1128.     last_symbol = bp;
  1129.     bp->tag = plhs[nrules]->tag;
  1130.     bp->class = NONTERM;
  1131.  
  1132.     if ((nitems += 2) > maxitems)
  1133.     expand_items();
  1134.     bpp = pitem + nitems - 1;
  1135.     *bpp-- = bp;
  1136.     while (bpp[0] = bpp[-1]) --bpp;
  1137.  
  1138.     if (++nrules >= maxrules)
  1139.     expand_rules();
  1140.     plhs[nrules] = plhs[nrules-1];
  1141.     plhs[nrules-1] = bp;
  1142.     rprec[nrules] = rprec[nrules-1];
  1143.     rprec[nrules-1] = 0;
  1144.     rassoc[nrules] = rassoc[nrules-1];
  1145.     rassoc[nrules-1] = TOKEN;
  1146. }
  1147.  
  1148.  
  1149. add_symbol()
  1150. {
  1151.     register int c;
  1152.     register bucket *bp;
  1153.     int s_lineno = lineno;
  1154.  
  1155.     c = *cptr;
  1156.     if (c == '\'' || c == '"')
  1157.     bp = get_literal();
  1158.     else
  1159.     bp = get_name();
  1160.  
  1161.     c = nextc();
  1162.     if (c == ':')
  1163.     {
  1164.     end_rule();
  1165.     start_rule(bp, s_lineno);
  1166.     ++cptr;
  1167.     return;
  1168.     }
  1169.  
  1170.     if (last_was_action)
  1171.     insert_empty_rule();
  1172.     last_was_action = 0;
  1173.  
  1174.     if (++nitems > maxitems)
  1175.     expand_items();
  1176.     pitem[nitems-1] = bp;
  1177. }
  1178.  
  1179.  
  1180. copy_action()
  1181. {
  1182.     register int c;
  1183.     register int i, n;
  1184.     int depth;
  1185.     int quote;
  1186.     char *tag;
  1187.     register FILE *f = action_file;
  1188.     int a_lineno = lineno;
  1189.     char *a_line = dup_line();
  1190.     char *a_cptr = a_line + (cptr - line);
  1191.  
  1192.     if (last_was_action)
  1193.     insert_empty_rule();
  1194.     last_was_action = 1;
  1195.  
  1196.     fprintf(f, "case %d:\n", nrules - 2);
  1197.     if (!lflag)
  1198.     fprintf(f, line_format, lineno, input_file_name);
  1199.     if (*cptr == '=') ++cptr;
  1200.  
  1201.     n = 0;
  1202.     for (i = nitems - 1; pitem[i]; --i) ++n;
  1203.  
  1204.     depth = 0;
  1205. loop:
  1206.     c = *cptr;
  1207.     if (c == '$')
  1208.     {
  1209.     if (cptr[1] == '<')
  1210.     {
  1211.         int d_lineno = lineno;
  1212.         char *d_line = dup_line();
  1213.         char *d_cptr = d_line + (cptr - line);
  1214.  
  1215.         ++cptr;
  1216.         tag = get_tag();
  1217.         c = *cptr;
  1218.         if (c == '$')
  1219.         {
  1220.         fprintf(f, "yyval.%s ", tag);
  1221.         ++cptr;
  1222.         FREE(d_line);
  1223.         goto loop;
  1224.         }
  1225.         else if (isdigit(c))
  1226.         {
  1227.         i = get_number();
  1228.         if (i > n) dollar_warning(d_lineno, i);
  1229.         fprintf(f, "yyvsp[%d].%s ", i - n, tag);
  1230.         FREE(d_line);
  1231.         goto loop;
  1232.         }
  1233.         else if (c == '-' && isdigit(cptr[1]))
  1234.         {
  1235.         ++cptr;
  1236.         i = -get_number() - n;
  1237.         fprintf(f, "yyvsp[%d].%s ", i, tag);
  1238.         FREE(d_line);
  1239.         goto loop;
  1240.         }
  1241.         else
  1242.         dollar_error(d_lineno, d_line, d_cptr);
  1243.     }
  1244.     else if (cptr[1] == '$')
  1245.     {
  1246.         if (ntags)
  1247.         {
  1248.         tag = plhs[nrules]->tag;
  1249.         if (tag == 0) untyped_lhs();
  1250.         fprintf(f, "yyval.%s ", tag);
  1251.         }
  1252.         else
  1253.         fprintf(f, "yyval ");
  1254.         cptr += 2;
  1255.         goto loop;
  1256.     }
  1257.     else if (isdigit(cptr[1]))
  1258.     {
  1259.         ++cptr;
  1260.         i = get_number();
  1261.         if (ntags)
  1262.         {
  1263.         if (i <= 0 || i > n)
  1264.             unknown_rhs(i);
  1265.         tag = pitem[nitems + i - n - 1]->tag;
  1266.         if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
  1267.         fprintf(f, "yyvsp[%d].%s ", i - n, tag);
  1268.         }
  1269.         else
  1270.         {
  1271.         if (i > n)
  1272.             dollar_warning(lineno, i);
  1273.         fprintf(f, "yyvsp[%d]", i - n);
  1274.         }
  1275.         goto loop;
  1276.     }
  1277.     else if (cptr[1] == '-')
  1278.     {
  1279.         cptr += 2;
  1280.         i = get_number();
  1281.         if (ntags)
  1282.         unknown_rhs(-i);
  1283.         fprintf(f, "yyvsp[%d]", -i - n);
  1284.         goto loop;
  1285.     }
  1286.     }
  1287.     if (isalpha(c) || c == '_' || c == '$')
  1288.     {
  1289.     do
  1290.     {
  1291.         putc(c, f);
  1292.         c = *++cptr;
  1293.     } while (isalnum(c) || c == '_' || c == '$');
  1294.     goto loop;
  1295.     }
  1296.     putc(c, f);
  1297.     ++cptr;
  1298.     switch (c)
  1299.     {
  1300.     case '\n':
  1301.     next_line:
  1302.     get_line();
  1303.     if (line) goto loop;
  1304.     unterminated_action(a_lineno, a_line, a_cptr);
  1305.  
  1306.     case ';':
  1307.     if (depth > 0) goto loop;
  1308.     fprintf(f, "\nbreak;\n");
  1309.     return;
  1310.  
  1311.     case '{':
  1312.     ++depth;
  1313.     goto loop;
  1314.  
  1315.     case '}':
  1316.     if (--depth > 0) goto loop;
  1317.     fprintf(f, "\nbreak;\n");
  1318.     return;
  1319.  
  1320.     case '\'':
  1321.     case '"':
  1322.     {
  1323.         int s_lineno = lineno;
  1324.         char *s_line = dup_line();
  1325.         char *s_cptr = s_line + (cptr - line - 1);
  1326.  
  1327.         quote = c;
  1328.         for (;;)
  1329.         {
  1330.         c = *cptr++;
  1331.         putc(c, f);
  1332.         if (c == quote)
  1333.         {
  1334.             FREE(s_line);
  1335.             goto loop;
  1336.         }
  1337.         if (c == '\n')
  1338.             unterminated_string(s_lineno, s_line, s_cptr);
  1339.         if (c == '\\')
  1340.         {
  1341.             c = *cptr++;
  1342.             putc(c, f);
  1343.             if (c == '\n')
  1344.             {
  1345.             get_line();
  1346.             if (line == 0)
  1347.                 unterminated_string(s_lineno, s_line, s_cptr);
  1348.             }
  1349.         }
  1350.         }
  1351.     }
  1352.  
  1353.     case '/':
  1354.     c = *cptr;
  1355.     if (c == '/')
  1356.     {
  1357.         putc('*', f);
  1358.         while ((c = *++cptr) != '\n')
  1359.         {
  1360.         if (c == '*' && cptr[1] == '/')
  1361.             fprintf(f, "* ");
  1362.         else
  1363.             putc(c, f);
  1364.         }
  1365.         fprintf(f, "*/\n");
  1366.         goto next_line;
  1367.     }
  1368.     if (c == '*')
  1369.     {
  1370.         int c_lineno = lineno;
  1371.         char *c_line = dup_line();
  1372.         char *c_cptr = c_line + (cptr - line - 1);
  1373.  
  1374.         putc('*', f);
  1375.         ++cptr;
  1376.         for (;;)
  1377.         {
  1378.         c = *cptr++;
  1379.         putc(c, f);
  1380.         if (c == '*' && *cptr == '/')
  1381.         {
  1382.             putc('/', f);
  1383.             ++cptr;
  1384.             FREE(c_line);
  1385.             goto loop;
  1386.         }
  1387.         if (c == '\n')
  1388.         {
  1389.             get_line();
  1390.             if (line == 0)
  1391.             unterminated_comment(c_lineno, c_line, c_cptr);
  1392.         }
  1393.         }
  1394.     }
  1395.     goto loop;
  1396.  
  1397.     default:
  1398.     goto loop;
  1399.     }
  1400. }
  1401.  
  1402.  
  1403. int
  1404. mark_symbol()
  1405. {
  1406.     register int c;
  1407.     register bucket *bp;
  1408.  
  1409.     c = cptr[1];
  1410.     if (c == '%' || c == '\\')
  1411.     {
  1412.     cptr += 2;
  1413.     return (1);
  1414.     }
  1415.  
  1416.     if (c == '=')
  1417.     cptr += 2;
  1418.     else if ((c == 'p' || c == 'P') &&
  1419.          ((c = cptr[2]) == 'r' || c == 'R') &&
  1420.          ((c = cptr[3]) == 'e' || c == 'E') &&
  1421.          ((c = cptr[4]) == 'c' || c == 'C') &&
  1422.          ((c = cptr[5], !IS_IDENT(c))))
  1423.     cptr += 5;
  1424.     else
  1425.     syntax_error(lineno, line, cptr);
  1426.  
  1427.     c = nextc();
  1428.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  1429.     bp = get_name();
  1430.     else if (c == '\'' || c == '"')
  1431.     bp = get_literal();
  1432.     else
  1433.     {
  1434.     syntax_error(lineno, line, cptr);
  1435.     /*NOTREACHED*/
  1436.     }
  1437.  
  1438.     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1439.     prec_redeclared();
  1440.  
  1441.     rprec[nrules] = bp->prec;
  1442.     rassoc[nrules] = bp->assoc;
  1443.     return (0);
  1444. }
  1445.  
  1446.  
  1447. read_grammar()
  1448. {
  1449.     register int c;
  1450.  
  1451.     initialize_grammar();
  1452.     advance_to_start();
  1453.  
  1454.     for (;;)
  1455.     {
  1456.     c = nextc();
  1457.     if (c == EOF) break;
  1458.     if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
  1459.         c == '"')
  1460.         add_symbol();
  1461.     else if (c == '{' || c == '=')
  1462.         copy_action();
  1463.     else if (c == '|')
  1464.     {
  1465.         end_rule();
  1466.         start_rule(plhs[nrules-1], 0);
  1467.         ++cptr;
  1468.     }
  1469.     else if (c == '%')
  1470.     {
  1471.         if (mark_symbol()) break;
  1472.     }
  1473.     else
  1474.         syntax_error(lineno, line, cptr);
  1475.     }
  1476.     end_rule();
  1477. }
  1478.  
  1479.  
  1480. free_tags()
  1481. {
  1482.     register int i;
  1483.  
  1484.     if (tag_table == 0) return;
  1485.  
  1486.     for (i = 0; i < ntags; ++i)
  1487.     {
  1488.     assert(tag_table[i]);
  1489.     FREE(tag_table[i]);
  1490.     }
  1491.     FREE(tag_table);
  1492. }
  1493.  
  1494.  
  1495. pack_names()
  1496. {
  1497.     register bucket *bp;
  1498.     register char *p, *s, *t;
  1499.  
  1500.     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
  1501.     for (bp = first_symbol; bp; bp = bp->next)
  1502.     name_pool_size += strlen(bp->name) + 1;
  1503.     name_pool = MALLOC(name_pool_size);
  1504.     if (name_pool == 0) no_space();
  1505.  
  1506.     strcpy(name_pool, "$accept");
  1507.     strcpy(name_pool+8, "$end");
  1508.     t = name_pool + 13;
  1509.     for (bp = first_symbol; bp; bp = bp->next)
  1510.     {
  1511.     p = t;
  1512.     s = bp->name;
  1513.     while (*t++ = *s++) continue;
  1514.     FREE(bp->name);
  1515.     bp->name = p;
  1516.     }
  1517. }
  1518.  
  1519.  
  1520. check_symbols()
  1521. {
  1522.     register bucket *bp;
  1523.  
  1524.     if (goal->class == UNKNOWN)
  1525.     undefined_goal(goal->name);
  1526.  
  1527.     for (bp = first_symbol; bp; bp = bp->next)
  1528.     {
  1529.     if (bp->class == UNKNOWN)
  1530.     {
  1531.         undefined_symbol_warning(bp->name);
  1532.         bp->class = TERM;
  1533.     }
  1534.     }
  1535. }
  1536.  
  1537.  
  1538. pack_symbols()
  1539. {
  1540.     register bucket *bp;
  1541.     register bucket **v;
  1542.     register int i, j, k, n;
  1543.  
  1544.     nsyms = 2;
  1545.     ntokens = 1;
  1546.     for (bp = first_symbol; bp; bp = bp->next)
  1547.     {
  1548.     ++nsyms;
  1549.     if (bp->class == TERM) ++ntokens;
  1550.     }
  1551.     start_symbol = ntokens;
  1552.     nvars = nsyms - ntokens;
  1553.  
  1554.     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1555.     if (symbol_name == 0) no_space();
  1556.     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1557.     if (symbol_value == 0) no_space();
  1558.     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1559.     if (symbol_prec == 0) no_space();
  1560.     symbol_assoc = MALLOC(nsyms);
  1561.     if (symbol_assoc == 0) no_space();
  1562.  
  1563.     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1564.     if (v == 0) no_space();
  1565.  
  1566.     v[0] = 0;
  1567.     v[start_symbol] = 0;
  1568.  
  1569.     i = 1;
  1570.     j = start_symbol + 1;
  1571.     for (bp = first_symbol; bp; bp = bp->next)
  1572.     {
  1573.     if (bp->class == TERM)
  1574.         v[i++] = bp;
  1575.     else
  1576.         v[j++] = bp;
  1577.     }
  1578.     assert(i == ntokens && j == nsyms);
  1579.  
  1580.     for (i = 1; i < ntokens; ++i)
  1581.     v[i]->index = i;
  1582.  
  1583.     goal->index = start_symbol + 1;
  1584.     k = start_symbol + 2;
  1585.     while (++i < nsyms)
  1586.     if (v[i] != goal)
  1587.     {
  1588.         v[i]->index = k;
  1589.         ++k;
  1590.     }
  1591.  
  1592.     goal->value = 0;
  1593.     k = 1;
  1594.     for (i = start_symbol + 1; i < nsyms; ++i)
  1595.     {
  1596.     if (v[i] != goal)
  1597.     {
  1598.         v[i]->value = k;
  1599.         ++k;
  1600.     }
  1601.     }
  1602.  
  1603.     k = 0;
  1604.     for (i = 1; i < ntokens; ++i)
  1605.     {
  1606.     n = v[i]->value;
  1607.     if (n > 256)
  1608.     {
  1609.         for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1610.         symbol_value[j] = symbol_value[j-1];
  1611.         symbol_value[j] = n;
  1612.     }
  1613.     }
  1614.  
  1615.     if (v[1]->value == UNDEFINED)
  1616.     v[1]->value = 256;
  1617.  
  1618.     j = 0;
  1619.     n = 257;
  1620.     for (i = 2; i < ntokens; ++i)
  1621.     {
  1622.     if (v[i]->value == UNDEFINED)
  1623.     {
  1624.         while (j < k && n == symbol_value[j])
  1625.         {
  1626.         while (++j < k && n == symbol_value[j]) continue;
  1627.         ++n;
  1628.         }
  1629.         v[i]->value = n;
  1630.         ++n;
  1631.     }
  1632.     }
  1633.  
  1634.     symbol_name[0] = name_pool + 8;
  1635.     symbol_value[0] = 0;
  1636.     symbol_prec[0] = 0;
  1637.     symbol_assoc[0] = TOKEN;
  1638.     for (i = 1; i < ntokens; ++i)
  1639.     {
  1640.     symbol_name[i] = v[i]->name;
  1641.     symbol_value[i] = v[i]->value;
  1642.     symbol_prec[i] = v[i]->prec;
  1643.     symbol_assoc[i] = v[i]->assoc;
  1644.     }
  1645.     symbol_name[start_symbol] = name_pool;
  1646.     symbol_value[start_symbol] = -1;
  1647.     symbol_prec[start_symbol] = 0;
  1648.     symbol_assoc[start_symbol] = TOKEN;
  1649.     for (++i; i < nsyms; ++i)
  1650.     {
  1651.     k = v[i]->index;
  1652.     symbol_name[k] = v[i]->name;
  1653.     symbol_value[k] = v[i]->value;
  1654.     symbol_prec[k] = v[i]->prec;
  1655.     symbol_assoc[k] = v[i]->assoc;
  1656.     }
  1657.  
  1658.     FREE(v);
  1659. }
  1660.  
  1661.  
  1662. pack_grammar()
  1663. {
  1664.     register int i, j;
  1665.     int assoc, prec;
  1666.  
  1667.     ritem = (short *) MALLOC(nitems*sizeof(short));
  1668.     if (ritem == 0) no_space();
  1669.     rlhs = (short *) MALLOC(nrules*sizeof(short));
  1670.     if (rlhs == 0) no_space();
  1671.     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1672.     if (rrhs == 0) no_space();
  1673.     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1674.     if (rprec == 0) no_space();
  1675.     rassoc = REALLOC(rassoc, nrules);
  1676.     if (rassoc == 0) no_space();
  1677.  
  1678.     ritem[0] = -1;
  1679.     ritem[1] = goal->index;
  1680.     ritem[2] = 0;
  1681.     ritem[3] = -2;
  1682.     rlhs[0] = 0;
  1683.     rlhs[1] = 0;
  1684.     rlhs[2] = start_symbol;
  1685.     rrhs[0] = 0;
  1686.     rrhs[1] = 0;
  1687.     rrhs[2] = 1;
  1688.  
  1689.     j = 4;
  1690.     for (i = 3; i < nrules; ++i)
  1691.     {
  1692.     rlhs[i] = plhs[i]->index;
  1693.     rrhs[i] = j;
  1694.     assoc = TOKEN;
  1695.     prec = 0;
  1696.     while (pitem[j])
  1697.     {
  1698.         ritem[j] = pitem[j]->index;
  1699.         if (pitem[j]->class == TERM)
  1700.         {
  1701.         prec = pitem[j]->prec;
  1702.         assoc = pitem[j]->assoc;
  1703.         }
  1704.         ++j;
  1705.     }
  1706.     ritem[j] = -i;
  1707.     ++j;
  1708.     if (rprec[i] == UNDEFINED)
  1709.     {
  1710.         rprec[i] = prec;
  1711.         rassoc[i] = assoc;
  1712.     }
  1713.     }
  1714.     rrhs[i] = j;
  1715.  
  1716.     FREE(plhs);
  1717.     FREE(pitem);
  1718. }
  1719.  
  1720.  
  1721. print_grammar()
  1722. {
  1723.     register int i, j, k;
  1724.     int spacing;
  1725.     register FILE *f = verbose_file;
  1726.  
  1727.     if (!vflag) return;
  1728.  
  1729.     k = 1;
  1730.     for (i = 2; i < nrules; ++i)
  1731.     {
  1732.     if (rlhs[i] != rlhs[i-1])
  1733.     {
  1734.         if (i != 2) fprintf(f, "\n");
  1735.         fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
  1736.         spacing = strlen(symbol_name[rlhs[i]]) + 1;
  1737.     }
  1738.     else
  1739.     {
  1740.         fprintf(f, "%4d  ", i - 2);
  1741.         j = spacing;
  1742.         while (--j >= 0) putc(' ', f);
  1743.         putc('|', f);
  1744.     }
  1745.  
  1746.     while (ritem[k] >= 0)
  1747.     {
  1748.         fprintf(f, " %s", symbol_name[ritem[k]]);
  1749.         ++k;
  1750.     }
  1751.     ++k;
  1752.     putc('\n', f);
  1753.     }
  1754. }
  1755.  
  1756.  
  1757. reader()
  1758. {
  1759.     write_section(banner);
  1760.     create_symbol_table();
  1761.     read_declarations();
  1762.     read_grammar();
  1763.     free_symbol_table();
  1764.     free_tags();
  1765.     pack_names();
  1766.     check_symbols();
  1767.     pack_symbols();
  1768.     pack_grammar();
  1769.     free_symbols();
  1770.     print_grammar();
  1771. }
  1772.